package demoMod.stsconsole.commands;

import demoMod.stsconsole.ConsoleEntry;
import demoMod.stsconsole.dungeons.AbstractDungeon;
import demoMod.stsconsole.enums.ErrType;
import demoMod.stsconsole.helpers.SubscriberReturnValueSaver;
import demoMod.stsconsole.interfaces.ConsumeRewardSubscriber;
import demoMod.stsconsole.rewards.AbstractReward;
import demoMod.stsconsole.rooms.AbstractRoom;

import java.lang.reflect.InvocationTargetException;
import java.util.Scanner;

public class Reward extends AbstractCommand {
    @Override
    public void execute(String[] args, Scanner sc) {
        if (args.length == 0) {
            this.errMsg(ErrType.WRONG_ARGUMENT);
            return;
        }
        switch (args[0]) {
            case "claim":
                if (args.length != 2) {
                    this.errMsg(ErrType.WRONG_ARGUMENT);
                    return;
                }
                try {
                    int index = Integer.parseInt(args[1]);
                    if (index < 0 || index >= AbstractDungeon.currDungeon.currMapNode.room.rewards.size()) {
                        this.errMsg(ErrType.WRONG_ARGUMENT);
                        return;
                    }
                    AbstractReward reward = AbstractDungeon.currDungeon.currMapNode.room.rewards.get(index);
                    if (reward.claimReward()) {
                        if (reward.mutexReward != null && AbstractDungeon.currDungeon.currMapNode.room.rewards.contains(reward.mutexReward)) {
                            reward.mutexReward.skipped();
                            AbstractDungeon.currDungeon.currMapNode.room.rewards.remove(reward.mutexReward);
                        }
                        AbstractDungeon.currDungeon.currMapNode.room.rewards.remove(index);
                    }
                } catch (NumberFormatException e) {
                    this.errMsg(ErrType.WRONG_ARGUMENT);
                }
                break;
            case "consume":
                if (args.length != 2) {
                    this.errMsg(ErrType.WRONG_ARGUMENT);
                    return;
                }
                try {
                    int index = Integer.parseInt(args[1]);
                    if (index < 0 || index >= AbstractDungeon.currDungeon.currMapNode.room.rewards.size()) {
                        this.errMsg(ErrType.WRONG_ARGUMENT);
                        return;
                    }
                    AbstractReward reward = AbstractDungeon.currDungeon.currMapNode.room.rewards.get(index);
                    SubscriberReturnValueSaver saver = new SubscriberReturnValueSaver();
                    saver.booleanValue = false;
                    ConsoleEntry.triggerSubscribers(ConsumeRewardSubscriber.class, "canConsume",
                            new Class[]{AbstractReward.class}, new Object[]{reward},
                            (method, params, subscriber) -> {
                                try {
                                    saver.booleanValue = saver.booleanValue || (boolean) method.invoke(subscriber, params);
                                } catch (IllegalAccessException | InvocationTargetException e) {
                                    e.printStackTrace();
                                }
                            }
                    );
                    if (saver.booleanValue) {
                        ConsoleEntry.triggerSubscribers(ConsumeRewardSubscriber.class, "accept",
                                new Class[]{AbstractReward.class}, new Object[]{reward});
                        if (reward.mutexReward != null && AbstractDungeon.currDungeon.currMapNode.room.rewards.contains(reward.mutexReward)) {
                            reward.mutexReward.skipped();
                            AbstractDungeon.currDungeon.currMapNode.room.rewards.remove(reward.mutexReward);
                        }
                        AbstractDungeon.currDungeon.currMapNode.room.rewards.remove(reward);
                        reward.skipped();
                    } else {
                        this.errMsg(ErrType.COMMAND_NOT_AVAILABLE);
                    }
                } catch (NumberFormatException e) {
                    this.errMsg(ErrType.WRONG_ARGUMENT);
                }
                break;
        }
    }

    @Override
    public boolean requiredPrompt(String currentPrompt) {
        return currentPrompt.contains("Dungeon") && AbstractDungeon.currDungeon.currMapNode.room.phase == AbstractRoom.RoomPhase.COMPLETED;
    }
}
